# -*- coding:utf-8 -*-
# 爬取实验楼课程文档
# python3.5
from bs4 import BeautifulSoup
import urllib
import urllib.request
import http.cookiejar

# 登录的主页面
hosturl = 'https://www.shiyanlou.com/login'  # 自己填写
# post数据接收和处理的页面（我们要向这个页面发送我们构造的Post数据）
posturl = 'https://www.shiyanlou.com/login'  # 从数据包中分析出，处理post请求的url

# 设置一个cookie处理器，它负责从服务器下载cookie到本地，并且在发送请求时带上本地的cookie
cj = http.cookiejar.LWPCookieJar()
cookie_support = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(cookie_support, urllib.request.HTTPHandler)
urllib.request.install_opener(opener)

# 打开登录主页面（他的目的是从页面下载cookie，这样我们在再送post数据时就有cookie了，否则发送不成功）
h = urllib.request.urlopen(hosturl)
h_html = h.read()

# 构造header，一般header至少要包含一下两项。这两项是从抓到的包里分析得出的。
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1',
           'Referer': 'https://www.shiyanlou.com/login'}
# 构造Post数据，也是从抓大的包里分析得出的。

# 取得csrf_token值  否则登录失败
# 形如 <input id="csrf_token" name="csrf_token" value="1476366242##dc0cf9e1f5af9d9c703dc62f1940f53f82a98352" type="hidden">
soup = BeautifulSoup(h_html)
csrf_token = soup.find(id='csrf_token').attrs['value']

postData = {'csrf_token': csrf_token,  # 1476366137##d88a7b89154130c7a6f4f31315a52b98d1df30d8
            'login': '*************',  # 你的用户名
            'next': '',
            'password': '********',  # 你的密码，密码可能是明文传输也可能是密文，如果是密文需要调用相应的加密算法加密
            'submit': '进入实验楼',  # 特有数据，不同网站可能不同
            }

# 需要给Post数据编码
postData = urllib.parse.urlencode(postData).encode('utf-8')

# 通过urllib2提供的request方法来向指定Url发送我们构造的数据，并完成登录过程
request = urllib.request.Request(posturl, postData, headers)
print(request)
response = urllib.request.urlopen(request)
text = response.read()

url_s1 = 'https://www.shiyanlou.com/courses/?course_type=all&tag=Python&page={page}'
url_courses = []
page = 1
url_document = []

# 抓取课程链接（简介 介绍）
while (True):
    html_1 = urllib.request.urlopen(
        "https://www.shiyanlou.com/courses/?course_type=all&tag=Python&page={page}".format(page=page))
    page += 1
    # 该网站 页码超上限则返回课程主页，故返回主页时，停止抓取课程链接
    if html_1.url == "https://www.shiyanlou.com/courses/":
        break
    html_doc = html_1.read()
    soup = BeautifulSoup(html_doc)
    for i in soup.find_all(class_='course-box'):
        url_courses.append('https://www.shiyanlou.com' + i.attrs['href'])

# 抓取课程页面链接（文档 正文）
for url in url_courses:
    html_2 = urllib.request.urlopen(url)
    html_doc = html_2.read()
    soup = BeautifulSoup(html_doc)
    for i in soup.find_all(class_="lab-id")[1:]:
        # https://www.shiyanlou.com/courses/561/labs/1886/document
        url_document.append(url + "/labs/" + i.attrs['data-lab-id'] + "/document")

# 通过链接抓取正文
# 源数据在<textarea>标签内 经js渲染后显示在页面<div id="preview" class="markdown-body">标签下
# 故采用phantomjs模拟浏览器渲染页面，并提取Dom(渲染后的正文内容)
import subprocess

for url in url_document:
    print("--- getting {url} ---".format(url=url))
    try:
        html_3 = urllib.request.urlopen(url)
    except urllib.error.HTTPError as e: #我的登录账号并没有买年费会员 404的就是付费内容。。。
        print(e)
        continue
    html_doc = html_3.read()
    f=open('doc_tmp.html','wb')
    f.write(html_doc)
    f.close()

    p = subprocess.Popen('phantomjs getDom.js {test_doc}'.format(test_doc='doc_tmp.html'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    #print(p.stdout.readlines())
    filename='_'.join(url.split('/')[3:])
    f=open('doc_dir/'+filename,'w',encoding='utf-8')
    for line in p.stdout.readlines():
        f.write(line.decode('utf8','ignore'),)
    f.close()
    retval = p.wait()
print('all done !!!!!!!!!!!!!!!!!!!!!!!')
